library(readxl)
library(tidyverse)
library(gt)

Daten

Der Datensatz “Kosten des Gesundheitswesens nach Leistungen” wird vom Bundesamt für Statistik (BFS) publiziert als MS Excel Datei hier publiziert. Die Daten wurden zuletzt am 31.10.2020 für das Jahr 2018 aktualisiert. Diese und weitere Metadaten sind in der MS Excel Datei ab Reihe 44 zu finden.

Daten importieren

Wir importieren die Datei in dem wir sie mit der Funkion download.file() herunterladen und in dem Ordner “data/raw” innerhalb unseres Projektes speichern. Die URL bezieht sich direkt auf den Download Link. Danach können wir die Daten mit der Funktion read_excel() in unsere Arbeitsumgebung importieren.

R Package {here}

Das R Package mit dem Namen here ist sehr hilfreich im Umgang mit Dateipfaden. Wenn wir in den File Manager unten rechts blicken sehen wir in diesem RStudio Project zwei Ordner:

  • analyse
  • data

Die Daten für das Projekt stecken im Ordner ‘data’. Die R Markdown Datei für die Analyse steckt im Ordner ‘analyse’. Um die Daten aus dem Ordner ‘data’ zu lesen, müssen die Dateipfade korrekt gesetzt sein. Standardmässig ist der aktuelle Pfad in R Markdown Dateien der Pfad an dem die Datei gespeichert ist, und nicht der Stammpfad des Projektes. Sobald eine R Markdown Datei und die zu importierenden Daten nicht am gleichen Ort liegen, müssen die Pfade angepasst werden.

Pfade unterscheiden sich zwischen Arbeitsgeräten, weshalb es sich nicht empfiehlt einen absoluten Pfad zu setzen, zum Beispiel:

  • read_excel(/Users/work/gitrepos/teaching-starter/demonstration/demo-03-tabellen/data/raw/je-d-14.05.01.03.xlsx)"

Dieses Skript würde nur auf diesem einen Arbeitsgerät problemlos und der Pfad müsste jeweils angepasst werden. Das here Package löst diese Problem mit der Funktion des selben Namen here(), welche den Pfad in der jeweiligen Arbeitsumgebung korrekt setzt.

library(readxl) # https://readxl.tidyverse.org/
library(here)

# was sehen wir?

download.file(url = "https://www.bfs.admin.ch/bfsstatic/dam/assets/14840808/master", 
              destfile = here("data/raw/je-d-14.05.01.03.xlsx"))

gesundheit <- read_excel(path = here("data/raw/je-d-14.05.01.03.xlsx"),
                         skip = 2, 
                         n_max = 44)

Daten aufräumen

Kosten als Kategorien (Summe der Sparten)

Hier ist der Code zum Daten aufräumen (Data tidying) bereits geschrieben. Der Code ist als eine lange Code Sequenz geschrieben, in welcher jeder Schritt kommentiert ist. Neu tauchen hier zwei Funktionen aus dem stringr Package auf, welches das Arbeiten mit Text unterstützt:

  • str_length()
  • str_replace()

Um mehr über das Arbeiten mit Text in R zu lernen, siehe hier:

# Starte mit Objekt gesundheit und speicher das Ergebnis als ein Objekt mit dem
# Namen gesundheit_total in deiner Arbeitsumgebung

gesundheit_total <- gesundheit %>% 
  
  # Entferne die erste Zeile
  slice(-1) %>% 
  
  # Geben den ersten beiden Spalten einen neuen Namen
  rename(kategorie_code = ...1,
         kategorie_name = ...2) %>% 
  
  # Filter alle Werte in der Spalte "kategorie_code", bei welchen die Länge des 
  # Textes (string) gleich 1 ist
  filter(str_length(kategorie_code) == 1) %>% 
  
  # Bringe die Daten von einem weiten in ein langes Format
  pivot_longer(cols = !c(kategorie_code, kategorie_name),  # drehe alle bis auf diese zwei Spalten
               names_to = "jahr",                          # Speicher die Namen in neuer Spalte "jahr"
               values_to = "mio_chf") %>%                  # Speicher die Werte in neuer Spalgte "mio_chf"
  
  # Mache eine Typumwandlung von character Variable auf numerische Varibale
  mutate(jahr = as.numeric(jahr))   %>% 
  
  # Ersetze Text mit einer Zahl und geschlossenen Klammer ')' durch leeren Text
  mutate(kategorie_name = str_replace(string = kategorie_name,
                                      # Regular Expression pattern für eine Zahl (d) und die Klammer )
                                      pattern = " \\d\\)", 
                                      replacement = ""))


# Erstelle einen Tibble für den Code und Namen der Leistungskategorien
leistungen <- gesundheit_total %>% 
  select(kategorie_code, kategorie_name) %>% 
  # Die Funktion distinct stammt aus dem dplyr Package und bewirkt das in einem
  # Datensatz nur eindeutige Reihen auftauchen (keine Wiederholungen)
  distinct()

Kosten als Sparten (keine Zusammenfassung)

In diesem Code Chunk sind die einzelnen Schritte zum Säubern von Daten in Untrschritte unterteilt. Dies hilft dabei jeden Schritt als ein einziges kleines Problem anzugehen und unterstützt auch bei einer möglichen Fehlersuche.

# Schritt 1
ges1 <- gesundheit %>% 
  slice(-1) %>% 
  rename(sparte_code = ...1,
         sparte_name = ...2)

# Schritt 2
ges2 <- ges1 %>% 
  mutate(kategorie_code = case_when(
    str_length(sparte_code) == 1 ~ sparte_code,
    TRUE ~ NA_character_
  )) 

# Schritt 3
ges3 <- ges2 %>% 
  relocate(kategorie_code) %>% 
  fill(kategorie_code) 

# Schritt 4
ges4 <- ges3 %>% 
  filter(str_length(sparte_code) > 1)

# Schritt 5
ges5 <- ges4 %>% 
  pivot_longer(cols = !kategorie_code:sparte_name,
               names_to = "jahr",
               values_to = "mio_chf", 
               values_drop_na = TRUE) %>% 
  mutate(jahr = as.numeric(jahr))

# Schritt 6
ges6 <- ges5 %>% 
  left_join(leistungen) 

# Schritt 7
ges7 <- ges6 %>% 
  mutate(sparte_name = str_replace(string = sparte_name,
                                   # Regular Expression pattern für eine Zahl (d) und die Klammer )
                                   pattern = " \\d\\)",
                                   replacement = "")) 
# Schritt 8
gesundheit_tidy_ab2010 <- ges7 %>% 
  relocate(kategorie_name, .after = "kategorie_code")

Was genau passiert in Schritt 7?

In der original MS Excel Tabelle sind einige Leistungen mit Fussnoten versehen. Diese Zahlen für die Fussnoten tauchen auch wieder auf wenn die Daten importiert werden, jeoch erfüllen sie nicht mehr ihren Zweck, da die eigentlichen Fussnoten fehlen. Die Funktion str_replace() ersetzt die Fussnoten mit einem leeren Text. Über die Funktione str_detect() können Spalten nach bestimmten Text Kriterien gefiltert werden. Im folgenden Code-chunk ist dies für drei Beispiele dokumentiert.

# Was passiert in Schritt 7? 

# Beispiel 1
# Regular expressions- Ein fortgeschrittenes Thema 

# Filter die Spalter sparte_name nach allen Werten welche dem Muster "\\d\\)" 
# Zum Bespiel: 1) 
# Mit \d wird eine Zahl identifiziert. Der zweite Backslash erstellt eine 
# "Escapezeichenfolge" und ist notwendig um das \d nicht als Text zu deuten
# Mit \\) wird das Zeichen ) identifiziert

ges6 %>% 
  filter(str_detect(string = sparte_name,
                    # Regular Expression Muster für eine Zahl (d) und die Klammer )
                    pattern = "\\d\\)")) 

# Beispiel 2 
# Filter über die Länge eine strings (Texts)

# Filter die Spalter sparte_code nach Text welcher länger ist als ein Zeichen
# Zum Beispiel L1 

ges1 %>% 
  filter(str_length(sparte_code) > 1)


# Beispiel 3
# Filter über einen Teil des Textes

# Filter die Spalte kategorie_name nach Text welcher den String 'pflege' 
# enthält

gesundheit_total %>% 
  filter(str_detect(kategorie_name, "pflege"))

Daten visualisieren mit `{plotly}

library(plotly)

plot_gesundheit_total <- gesundheit_total %>% 
  mutate(mio_chf = round(mio_chf, 0)) %>% 
  
  # Plot mit ggplot erstellen
  ggplot(aes(x = jahr, y = mio_chf, color = kategorie_name)) +
  geom_point() +
  geom_path() +
  scale_color_brewer(type = "qual") +
  labs(title = "Kosten des Gesundheitswesens nach Leistungen \nSchweiz, National, 1995 bis 2018",
       x = "Jahr",
       y = "Millionen Franken [CHF]",
       color = "Leistung") +
  theme_minimal()

ggplotly(plot_gesundheit_total)

Für Alle die mehr lernen wollen: https://plotly-r.com/index.html

Daten tabellarisch darstellen

Mit dem {gt} Package

# Daten eingrenzen 
gesundheit_sparte_tab <- gesundheit_tidy_ab2010 %>% 
  select(-ends_with("code")) %>% 
  pivot_wider(names_from = "jahr", values_from = "mio_chf") 

# Variablen Namen der Jahreszahlen speichern
jahr_var <- gesundheit_sparte_tab %>% 
  select(`2010`:`2018`) %>% 
  names()
# Tabelle darstellen

# Schritt 1
gesundheit_sparte_tab %>% 
  gt(rowname_col = "sparte_name",
     groupname_col = "kategorie_name") %>% 
  tab_header(title = "Kosten des Gesundheitswesens nach Leistungen 2010 bis 2018") %>% 
  tab_spanner(label = "In Millionen Franken",
              columns = vars(jahr_var)) %>% 
  fmt_number(columns = vars(jahr_var),
             decimals = 0,
             sep_mark =  " ") %>% 
  tab_source_note(source_note = md("**Quelle:**  Bundesamt für Statistik (BFS) – 
                                   Kosten und Finanzierung des Gesundheitswesens")) %>% 
  tab_source_note(source_note = md("**Datenbezug:** 
                                   [opendata.swiss](https://opendata.swiss/de/dataset/kosten-des-gesundheitswesens-nach-leistungen6)")) %>% 
  tab_footnote(footnote = "Neuberechnung ab 2010. Retropolation auf Basis bisheriger Wachstumsraten für die Jahre 1995-2009.", 
               locations = cells_title()) %>% 
  summary_rows(groups = TRUE,
               columns = jahr_var,
               fns = list(Summe = "sum"),
               formatter = fmt_number,
               decimals = 0,
               sep_mark = " ") %>%
  grand_summary_rows(columns = jahr_var,
                     fns = list(Total = "sum"),
                     formatter = fmt_number,
                     decimals = 0,
                     sep_mark = " ") %>%
  tab_options(
    row_group.background.color = "#E4E7F6",
    summary_row.background.color = "#DCDCDC",
    grand_summary_row.background.color = "#808080", 
  )
Kosten des Gesundheitswesens nach Leistungen 2010 bis 20181
In Millionen Franken
2010 2011 2012 2013 2014 2015 2016 2017 2018
Stationäre Kurativbehandlung
Stationäre somatische Akutbehandlung 11 696 11 878 12 397 12 946 13 118 13 469 13 832 13 786 13 622
Stationäre Psychiatriebehandlung 1 674 1 699 1 771 1 836 1 819 1 905 1 912 1 917 1 908
Stationäre Geburtshausbehandlung 3 5 8 9 10 12 14 16 17
Summe 13 373 13 583 14 176 14 791 14 947 15 386 15 758 15 718 15 548
Ambulante Kurativbehandlung
Ambulante somatische Akutbehandlung im Spital 4 226 4 315 4 717 4 969 5 427 5 677 6 136 6 307 6 409
Ärztliche Behandlung, ambulant, Einzelleistungen 4 509 4 317 4 273 4 343 4 405 4 638 4 711 4 690 3 871
Ärztliche Behandlung, ambulant, Managed Care 1 582 1 984 2 277 2 578 2 839 3 195 3 400 3 659 3 797
Zahnbehandlung 4 022 4 089 4 171 4 251 4 347 4 279 4 256 4 473 4 684
Ambulante Psychiatrie- und Psychologiebehandlung, kurativ 864 854 923 987 1 121 1 169 1 263 1 301 1 391
Ambulante Geburtshilfe, ambulante Geburtshausbehandlung 53 58 61 65 73 84 106 116 125
Andere kurative Therapien 552 491 503 496 468 500 566 563 477
Summe 15 808 16 109 16 924 17 688 18 681 19 541 20 436 21 108 20 753
Rehabilitation
Stationäre Rehabilitation 1 692 1 698 1 695 1 719 1 678 1 817 1 833 1 834 1 892
Ambulante Rehabilitation, nicht-psychosomatisch 1 071 1 090 1 138 1 206 1 401 1 561 1 728 1 829 1 931
Summe 2 764 2 789 2 834 2 925 3 080 3 378 3 560 3 663 3 823
Langzeitpflege
Langzeitpflege in Institutionen 10 952 11 491 11 950 12 264 12 548 12 873 13 031 13 376 13 674
Häusliche Langzeitpflege, engerer Sinn: Pflege 1 637 1 765 1 882 1 991 2 080 2 257 2 417 2 566 2 700
Häusliche Langzeitpflege, weiterer Sinn: Haushalt etc. 0 0 0 0 0 0 0 0 0
Summe 12 589 13 257 13 832 14 255 14 628 15 129 15 449 15 943 16 374
Unterstützende Dienstleistungen
Laboranalysen 1 025 1 103 1 131 1 319 1 455 1 559 1 717 1 871 1 939
Transport und Rettung 304 334 346 401 406 438 465 460 476
Radiologie 766 799 843 951 1 040 1 061 1 110 1 132 993
Gemeinwirtschaftliche Leistung: Lehre und Forschung 754 736 852 931 925 986 1 125 1 159 1 237
Gemeinwirtschaftliche Leistung: Sonstige 473 745 793 812 940 994 1 136 1 406 1 544
Summe 3 322 3 717 3 966 4 414 4 767 5 037 5 553 6 028 6 188
Gesundheitsgüter
Medikamente, stationär 572 556 520 518 478 503 507 511 531
Medikamente, ambulant, verschreibungspflichtig 5 399 5 490 5 632 5 702 5 801 6 106 6 508 6 907 6 860
Medikamente, ambulant, frei verkäuflich 1 664 1 678 1 695 1 777 1 789 1 900 2 030 1 999 2 078
Verbrauchsprodukte 635 635 651 679 704 696 700 672 763
Therapeutische Apparate 1 814 1 739 1 682 1 743 1 831 1 894 1 957 2 000 1 981
Summe 10 083 10 098 10 181 10 419 10 604 11 100 11 702 12 088 12 214
Prävention
Primärprävention: Sucht 287 270 278 320 313 330 308 322 440
Primärprävention: Psychische Gesundheit, Schulgesundheit 184 179 173 173 171 167 181 183 182
Primärprävention: Unfälle und Verletzungen 120 138 130 130 128 129 128 121 137
Primärprävention: Lebensmittelsicherheit 172 171 169 170 175 180 188 157 152
Primärprävention: Aufklärung der Bevölkerung/Zielgruppen 193 171 169 170 173 173 186 233 267
andere Prävention 751 766 781 818 891 897 904 921 948
Summe 1 707 1 696 1 700 1 781 1 852 1 878 1 894 1 937 2 126
Verwaltung
Verwaltung öffentliches Gesundheitswesen 494 509 495 497 477 473 493 515 522
Verwaltung Sozialversicherungen 1 579 1 658 1 739 1 790 1 809 1 832 1 942 1 961 1 952
Verwaltung Privatversicherungen 845 830 665 558 584 630 668 681 742
Summe 2 918 2 996 2 899 2 845 2 870 2 935 3 103 3 157 3 216
Total 62 565 64 243 66 512 69 118 71 429 74 385 77 455 79 643 80 242
Quelle: Bundesamt für Statistik (BFS) – Kosten und Finanzierung des Gesundheitswesens
Datenbezug: opendata.swiss

1 Neuberechnung ab 2010. Retropolation auf Basis bisheriger Wachstumsraten für die Jahre 1995-2009.